bitkeeper revision 1.959.1.7 (40d0b7e204hRazr8_qoesp7P0oZMUw)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 16 Jun 2004 21:13:06 +0000 (21:13 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 16 Jun 2004 21:13:06 +0000 (21:13 +0000)
Extend xm to support most of the control interface and
get 'xm create' closer to working.

tools/examples/xm_dom_control.py
tools/xenmgr/lib/XendClient.py
tools/xenmgr/lib/XendDomain.py
tools/xenmgr/lib/XendDomainInfo.py
tools/xenmgr/lib/xm/create.py
tools/xenmgr/lib/xm/main.py
tools/xenmgr/lib/xm/opts.py
tools/xenmgr/netfix
tools/xenmgr/xend

index da30244652bc710c128991e03bdf432e36d032cc..8d1885be88a6f836627968868fa6e0a3e3c764b9 100755 (executable)
@@ -8,6 +8,7 @@ import os
 import os.path
 import signal
 
+from xenmgr import sxp
 from xenmgr.XendClient import server
 
 # usage: xc_dom_control [command] <params>
@@ -131,13 +132,13 @@ elif cmd == 'list':
     for dom in server.xend_domains():
         info = server.xend_domain(dom)
         d = {}
-        d['dom'] = dom
-        d['name'] = sxp.get_child_value(info, 'name', '??')
-        d['mem'] = int(sxp.get_child_value(info, 'memory', '0'))
-        d['cpu'] = int(sxp.get_child_value(info, 'cpu', '0'))
-        d['state'] = sxp.get_child_value(info, 'state', '??')
-        d['cpu_time'] = sxp.get_child_value(info, 'cpu_time', '0')
-        print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)8d"
+        d['dom'] = int(dom)
+        d['name'] = sxp.child_value(info, 'name', '??')
+        d['mem'] = int(sxp.child_value(info, 'memory', '0'))
+        d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
+        d['state'] = sxp.child_value(info, 'state', '??')
+        d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0')
+        print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)8.2f"
                % d)
 
 elif cmd == 'unwatch':
index feed16a7defdd8741b0596a8b017129d613c5b56..76f49f49bd98abe3e6a6da45eaa0d53196c219eb 100644 (file)
@@ -97,7 +97,7 @@ def xend_request(url, method, data=None):
     #hdr['Accept'] = 'text/html,text/plain'
     conn = httplib.HTTPConnection(ulocation)
     #conn.response_class = Foo
-    conn.set_debuglevel(1)
+    if DEBUG: conn.set_debuglevel(1)
     conn.request(method, upath, args, hdr)
     resp = conn.getresponse()
     if DEBUG: print resp.status, resp.reason
@@ -118,10 +118,7 @@ def xend_request(url, method, data=None):
     #    val = val[1]
     if isinstance(val, types.ListType) and sxp.name(val) == 'err':
         raise RuntimeError(val[1])
-    if DEBUG: print '**val='
-    #sxp.show(val); print
-    PrettyPrint.prettyprint(val)
-    if DEBUG: print '**'
+    if DEBUG: print '**val='; sxp.show(val); print
     return val
 
 def xend_get(url, args=None):
@@ -334,7 +331,9 @@ def main(argv):
     if not fn.startswith('xend'):
         fn = 'xend_' + fn
     args = argv[2:]
-    getattr(server, fn)(*args)
+    val = getattr(server, fn)(*args)
+    PrettyPrint.prettyprint(val)
+    print
 
 if __name__ == "__main__":
     main(sys.argv)
index 9f7e143639dc7043068bdad048a00ac7eb766a97..94afe3e87d0d494e77496b9f07e313850078e44a 100644 (file)
@@ -66,11 +66,11 @@ class XendDomain:
                 print "dom=", domid, "del"
                 self._delete_domain(domid)
         print "doms:"
-        for d in self.domain.values(): print d
+        for d in self.domain.values(): print 'dom', d
         print "refresh..."
         self.refresh()
         print "doms:"
-        for d in self.domain.values(): print d
+        for d in self.domain.values(): print 'dom', d
 
     def sync(self):
         """Sync domain db to disk.
@@ -162,7 +162,7 @@ class XendDomain:
         else:
             d = self.domain.get(id)
             if d:
-                d.update(dominfo)
+                d.update(dominfo[0])
 
     def domain_ls(self):
         # List domains.
index 84def89b81b14bc65d06658fd66fbd0fc1eea353..2cc2ffd8c4be37d4a6afe29132b6badc167860bb 100644 (file)
@@ -113,7 +113,7 @@ class XendDomainInfo:
         if self.info:
             run = (self.info['running'] and 'r') or '-'
             stop = (self.info['stopped'] and 's') or '-'
-            state = run + state
+            state = run + stop
             sxpr.append(['cpu', self.info['cpu']])
             sxpr.append(['state', state])
             sxpr.append(['cpu_time', self.info['cpu_time']/1e8])
index e173a548dc624fc5ff0083c498363ea20e6fc12d..863227ad4cbfb78c6e1fd1e761a48b51db959b80 100644 (file)
@@ -40,7 +40,8 @@ def set_var(opt, k, v):
 
 opts.opt('define', short='D', val='VAR=VAL',
          fn=set_var, default=None,
-         use="Set a variable before loading defaults,e.g. '-D vmid=3;ip=1.2.3.4'.")
+         use="""Set variables before loading defaults, e.g. '-D vmid=3;ip=1.2.3.4'
+         to set vmid and ip.""")
 
 opts.opt('dryrun', short='n',
          fn=set_true, default=0,
@@ -71,6 +72,10 @@ opts.opt('disk', short='d', val='phy:DEV,VDEV,MODE',
          is exported to the domain as VDEV. The disk is read-only if MODE is r,
          read-write if mode is 'w'.""")
 
+opts.opt('pci', val='BUS,DEV,FUNC',
+         fn=append_value, default=[],
+         use="""Add a PCI device to a domain.""")
+
 opts.opt('ipaddr', short='i', val="IPADDR",
          fn=append_value, default=[],
          use="Add an IP address to the domain.")
@@ -82,7 +87,7 @@ opts.opt('mac', short='M', val="MAC",
          are allocated a random address.""")
 
 opts.opt('nics', val="N",
-         fn=set_int, default="1",
+         fn=set_int, default=1,
          use="Set the number of network interfaces.")
 
 opts.opt('vnet', val='VNET',
@@ -101,7 +106,7 @@ opts.opt('extra', short='E', val="ARGS",
          use="Set extra arguments to append to the kernel command line.")
 
 opts.opt('ip', short='I', val='IPADDR',
-         fn=set_value, default=[],
+         fn=set_value, default='',
          use="Set the kernel IP interface address.")
 
 opts.opt('gateway', val="IPADDR",
@@ -138,7 +143,7 @@ def strip(pre, s):
     else:
         return s
 
-def make_domain_config(opts):
+def make_config(opts):
     
     config = ['config',
               ['name', opts.name ],
@@ -151,10 +156,10 @@ def make_domain_config(opts):
     if opts.ramdisk:
         config_image.append([ 'ramdisk', os.path.abspath(opts.ramdisk) ])
     if opts.cmdline_ip:
-        cmdline_ip = strip("ip=", opts.cmdline_ip)
+        cmdline_ip = strip('ip=', opts.cmdline_ip)
         config_image.append(['ip', cmdline_ip])
     if opts.root:
-        cmdline_root = strip("root=", opts.root)
+        cmdline_root = strip('root=', opts.root)
         config_image.append(['root', opts.root])
     if opts.extra:
         config_image.append(['args', opts.extra])
@@ -173,7 +178,7 @@ def make_domain_config(opts):
         config_devs.append(['device', config_pci])
 
     for idx in range(0, opts.nics):
-        config_vif = ['vif' ['@', ['id', 'vif%d' % idx]]]
+        config_vif = ['vif', ['@', ['id', 'vif%d' % idx]]]
         if idx < len(opts.mac):
             config_vif.append(['mac', opts.mac[idx]])
         config_devs.append(['device', config_vif])
@@ -203,10 +208,11 @@ def preprocess_disk(opts):
     disk = []
     for v in opts.disk:
         d = v.split(',')
+        print 'disk', v, d
         if len(d) != 3:
             opts.err('Invalid disk specifier: ' + v)
         disk.append(d)
-    opts.disk = d
+    opts.disk = disk
 
 def preprocess_pci(opts):
     if not opts.pci: return
@@ -246,7 +252,7 @@ def preprocess(opts):
     preprocess_ip(opts)
     preprocess_nfs(opts)
          
-def make_domain(config):
+def make_domain(opts, config):
     """Create, build and start a domain.
     Returns: [int] the ID of the new domain.
     """
@@ -281,7 +287,10 @@ def main(argv):
         opts.usage()
     preprocess(opts)
     config = make_config(opts)
-    make_domain(opts, config)
+    if opts.dryrun:
+        PrettyPrint.prettyprint(config)
+    else:
+        make_domain(opts, config)
         
 if __name__ == '__main__':
     main(sys.argv)
index 1810c8dde0e05ed47f3cf5b823b41072587c80c5..4c70717521961709475cfca6a346e4cfc47214e7 100644 (file)
@@ -2,8 +2,8 @@
 import string
 import sys
 
+from xenmgr import sxp
 from xenmgr.XendClient import server
-
 from xenmgr.xm import create, shutdown
 
 class Xm:
@@ -55,7 +55,7 @@ class Xm:
     def xm_save(self, help, args):
         """Save domain state to file."""
         if help:
-            print "save DOM FILE"
+            print args[0], "DOM FILE"
             print "\nSave domain with id DOM to FILE."
             return
         if len(args) < 3: self.err("%s: Missing arguments" % args[0])
@@ -66,23 +66,31 @@ class Xm:
     def xm_restore(self, help, args):
         """Create a domain from a saved state."""
         if help:
-            print "restore FILE"
+            print args[0], "FILE"
             print "\nRestore a domain from FILE."
         if len(args) < 2: self.err("%s: Missing file" % args[0])
         server.xend_domain_restore(dom, None, filename)
 
     def xm_ls(self, help, args):
         """List domains."""
-        if help: self.help('xm_ls'); return
+        if help: self.help('xm_' + args[0]); return
         doms = server.xend_domains()
+        print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
         for dom in doms:
-            d = server.domain(dom)
-            print d
+            info = server.xend_domain(dom)
+            d = {}
+            d['dom'] = int(dom)
+            d['name'] = sxp.child_value(info, 'name', '??')
+            d['mem'] = int(sxp.child_value(info, 'memory', '0'))
+            d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
+            d['state'] = sxp.child_value(info, 'state', '??')
+            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
+            print ("%(dom)-4d %(name)-16s %(mem)4d     %(cpu)3d %(state)5s %(cpu_time)10.2f" % d)
 
     def xm_halt(self, help, args):
         """Terminate a domain immediately."""
         if help:
-            print 'halt DOM'
+            print args[0], 'DOM'
             print '\nTerminate domain DOM immediately.'
             return
         if len(args) < 2: self.err("%s: Missing domain" % args[0])
@@ -96,7 +104,7 @@ class Xm:
     def xm_stop(self, help, args):
         """Stop execution of a domain."""
         if help:
-            print 'stop DOM'
+            print args[0], 'DOM'
             print '\nStop execution of domain DOM.'
             return
         if len(args) < 2: self.err("%s: Missing domain" % args[0])
@@ -106,7 +114,7 @@ class Xm:
     def xm_start(self, help, args):
         """Start execution of a domain."""
         if help:
-            print 'start DOM'
+            print args[0], 'DOM'
             print '\nStart execution of domain DOM.'
             return
         if len(args) < 2: self.err("%s: Missing domain" % args[0])
@@ -116,28 +124,83 @@ class Xm:
     def xm_pincpu(self, help, args):
         """Pin a domain to a cpu. """
         if help:
-            print 'pincpu DOM CPU'
+            print args[0],'DOM CPU'
             print '\nPin domain DOM to cpu CPU.'
             return
-        pass
+        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
+        v = map(int, args[1:3])
+        server.xend_domain_pincpu(*v)
+
+    def xm_vif_stats(self, help, args):
+        """Get stats for a virtual interface."""
+        if help:
+            print args[0], 'DOM VIF'
+            print '\nGet stats for interface VIF on domain DOM.'
+            return
+        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
+        v = map(int, args[1:3])
+        print server.xend_domain_vif_stats(*v)
+
+    def xm_vif_rate(self, help, args):
+        """Set or get vif rate params."""
+        if help:
+            print args[0], "DOM VIF [BYTES USECS]"
+            print '\nSet or get rate controls for interface VIF on domain DOM.'
+            return
+        n = len(args)
+        if n == 3:
+            v = map(int, args[1:n])
+            print server.xend_domain_vif_scheduler_get(*v)
+        elif n == 5:
+            v = map(int, args[1:n])
+            server.xend_domain_vif_scheduler_set(*v)
+        else:
+            self.err("%s: Invalid argument(s)" % args[0])
 
     def xm_bvt(self, help, args):
-        pass
+        """Set BVT scheduler parameters."""
+        if help:
+            print args[0], "DOM MCUADV WARP WARPL WARPU"
+            print '\nSet Borrowed Virtual Time scheduler parameters.'
+            return
+        if len(args) != 6: self.err("%s: Invalid argument(s)" % args[0])
+        v = map(int, args[1:6])
+        server.xend_domain_cpu_bvt_set(*v)
 
     def xm_bvtslice(self, help, args):
-        pass
+        """Set the BVT scheduler slice."""
+        if help:
+            print args[0], 'SLICE'
+            print '\nSet Borrowed Virtual Time scheduler slice.'
+            return
+        if len(args) < 2: self.err('%s: Missing slice' % args[0])
+        server.xend_node_cpu_bvt_slice_set(slice)
 
     def xm_atropos(self, help, args):
-        pass
+        """Set atropos parameters."""
+        if help:
+            print args[0], "DOM PERIOD SLICE LATENCY XTRATIME"
+            print "\nSet atropos parameters."
+            return
+        if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
+        v = map(int, args[1:5])
+        server.xend_domain_cpu_atropos_set(*v)
 
-    def xm_rrslice(self, help, args):
-        pass
+    def xm_rrobin(self, help, args):
+        """Set round robin slice."""
+        if help:
+            print args[0], "SLICE"
+            print "\nSet round robin scheduler slice."
+            return
+        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
+        slice = int(args[1])
+        server.xend_node_rrobin_set(slice)
 
     def xm_info(self, help, args):
         """Get information about the xen host."""
         if help: self.help('xm_info'); return
         info = server.xend_node()
-        for x in info:
+        for x in info[1:]:
             print "%-23s:" % x[0], x[1]
 
     def xm_console(self, help, args):
index 61374cbf928080ea98342e9a066f38ed9c2e7036..7b32daeae23aa1775cb5e546ced2aace9fe1e393 100644 (file)
@@ -2,6 +2,7 @@ from getopt import getopt
 import os
 import os.path
 import sys
+import types
 
 class Opt:
     def __init__(self, opts, name, short=None, long=None,
@@ -78,10 +79,14 @@ class Opt:
         else:
             return 0
 
+    def specified(self):
+        return self.specified_opt
+
 class Opts:
     def __init__(self, use=None):
         self._usage = use
         self._options = []
+        self._options_map = {}
         self._argv = []
         self._vals = {}
         self._globals = {}
@@ -90,8 +95,16 @@ class Opts:
     def opt(self, name, **args):
         x = Opt(self, name, **args)
         self._options.append(x)
+        self._options_map[name] = x
         return x
 
+    def getopt(self, name):
+        return self._options_map.get(name)
+
+    def specified(self, name):
+        opt = self.getopt(name)
+        return opt and opt.specified()
+
     def setvar(self, name, val):
         self._globals[name] = val
 
@@ -140,28 +153,31 @@ class Opts:
             opt.show()
 
     def load_defaults(self):
-        print 'load_defaults>', 'defaults=', self.defaults
-        print 'load_defaults>', 'path=', self.path
         for x in [ '' ] + self.path.split(':'):
-            print 'load_defaults>', 'x=', x, 'defaults=', self.defaults
             if x:
                 p = os.path.join(x, self.defaults)
             else:
                 p = self.defaults
-            if os.stat(p):
+            if os.path.exists(p):
                 self.load(p)
                 break
         else:
             self.err("Cannot open defaults file %s" % self.defaults)
 
     def load(self, defaults):
-        print 'load>', 'defaults=', defaults
         self._globals['sys'] = sys
         self._globals['config_file'] = defaults
         execfile(defaults, self._globals, self._locals)
-        print 'load>', 'globals=', self._globals
-        print 'load>', 'locals=', self._locals
-            
+        vtypes = [ types.StringType,
+                   types.ListType,
+                   types.IntType,
+                   types.FloatType
+                   ]
+        for (k, v) in self._locals.items():
+            if self.specified(k): continue
+            if not(type(v) in vtypes): continue
+            print 'SET ', k, v
+            setattr(self, k, v)
 
 def set_true(opt, k, v):
     opt.set(1)
index fcde6292cb17ff6a69c51f64abbb68ef9d36afa2..70bc1094bd22ae3167f1ad1ee1d85f5767244199 100644 (file)
@@ -1,4 +1,5 @@
 #!/usr/bin/python
+#  -*- mode: python; -*-
 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
 #============================================================================
 # Move the IP address from eth0 onto the Xen bridge (nbe-br).
index f2355f1e515e0a48297cdbd4843b2e25abdaafab..e575eeccd561552a105e5a3988b7faa778ff37a7 100644 (file)
@@ -1,4 +1,5 @@
 #!/usr/bin/python
+#  -*- mode: python; -*-
 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
 
 """Xen management daemon. Lives in /usr/sbin.